<?php

include_once './log4php/Logger.php';
include_once './Utils.php';

Logger::configure('./log4j.properties');

/**
 * The default locale to be used if not specified.
 */
define('DEFAULT_LOCALE', 'en_EN');

date_default_timezone_set("UTC"); 

/**
 * Class I18N is responsible for the internationalization => parse the ini file holding texts according to the locale.
 */
class I18N {
    public static $pathAndPrefix = './resources/messages/messages_';
    /**
     * Path to the default config file holding the default message texts.
     */
    public static $pathToDefault = './resources/messages/messages_en_EN.ini';
    public static $defaultMessages = null;
    
    public $locale;
    /**
     * Array holding the messages.
     */
    private $messages = array();

    private static $log = NULL;

    private static function getLogger() {
        if (self::$log == NULL) {
            self::$log = Logger::getLogger(__CLASS__);
        }

        return self::$log;
    }

    /**
     * Constructs a new I18N instance.
     * 
     * @param object $locale [optional]
     * @return 
     */
    private function __construct($locale=DEFAULT_LOCALE) {
        self::getLogger()->debug('[START] I18N.php, args: ' . Utils::toString(func_get_args()));

        $this->locale = $locale;
        $this->messages = array_merge(self::$defaultMessages, $this->parse(self::$pathAndPrefix . $locale . '.ini'));
    }
    
    /**
     * Parses the ini file at the specified path and returns the associative array according to the parsed file.
     * 
     * @param object $path
     * @return 
     */
    private static function parse($path) {
        if (!file_exists($path)) {
            self::getLogger()->warn("Unsupported locale - non existing language config file: $path");
            $_COOKIE['locale'] = null;
            return array(); // empty array
        } 
        
        $messagesArray = parse_ini_file($path);
                        
        if (!$messagesArray) {
            self::getLogger()->error("An error occured while parsing the messages file: " . $path);
            return array(); // empty array
        }        
        return $messagesArray;
    }
    
    /**
     * Returns the message related to the given key.
     * If no message associated to the given key, then the key is returned.
     * 
     * @param object $key
     * @param integer $index in case of array value the index of the requested value
     * @return 
     */
    private function getString($key, $index=0) {
        $value = isset($this->messages[$key]) ? $this->messages[$key] : null;
        
        if ($value==null) {
            return $key;
        }
        
        if (is_array($value)) {
            $value = $value[$index];
        }
        
        return $value;
    }
    
    /**
     * Returns the singleton instance of the I18N class.
     * If it doesn't exist then it is created.
     * 
     * @param string $locale like 'en_EN', 'fi_FI', etc.
     * @param boolean $reload whether to force to reload the messages
     * @return 
     */
    private static function getInstance($locale=DEFAULT_LOCALE, $reload=false) {
        if (self::$defaultMessages===null) {
            self::$defaultMessages = self::parse(self::$pathToDefault);
        }
        
        static $instance = null;        
        if ($reload || $instance===null || $instance->locale!=$locale) {
            $instance = new I18N($locale);
        }
        
        return $instance;
    }

    /**
     * Returns the message according to the given key.
     * If the cookie 'locale' is present, the its value is used to select the language.
     * If no such language is supportedor not present then the default english is used.
     *
     * @param object $key
     * @param integer $index in case of array value the index of the requested value
     * @return
     */
    static public function getMessage($key, $index=0) {
        $locale = NULL;
        if (isset($_COOKIE['locale'])) {
            $locale = $_COOKIE['locale'];
            return I18N::getInstance($locale)->getString($key, $index);
        }

        return I18N::getInstance()->getString($key, $index);
    }

    /**
     * Converts unix time (EPOCH) to form '...  ago'
     *
     * @param integer $unix_date UNIX EPOCH time
     * @param boolean $html_format if true, then HTML entities are used (e.g. ' ' => '&nbsp;'). Default is true.
     * @return
     */
    static function epochToAgo($unix_date, $html_format=TRUE) {
        if(empty($unix_date)) {
            return self::getMessage('time.unknown');
        }

        $periods         = array("second", "minute", "hour", "day", "week", "month", "year", "decade");
        $lengths         = array("60","60","24","7","4.35","12","10");

        $now             = time();
        $difference     = $now - $unix_date;

        for($j = 0; $difference >= $lengths[$j] && $j < count($lengths)-1; $j++) {
            $difference /= $lengths[$j];
        }

        $difference = round($difference);

        return $difference . ($html_format ? '&nbsp;' : ' ') . self::getMessage('time.' . $periods[$j], ($difference!=1 ? 1 : 0)) . ($html_format ? '&nbsp;' : ' ') . self::getMessage('time.ago');
    }
    
}

?>